﻿using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Special;
using Fuse8.DomainFramework.Common;
using Fuse8.DomainFramework.DataAccess.SqlDatabase;
using System;
using System.Data.SqlClient;
using System.Linq;

namespace Fuse8.ContentManagementFramework.DataAccess.SqlAccess.Mappers
{
    public class CmsPageContainerDataMapper : BaseSqlEntityDataMapper<CmsPageContainer, int>
    {
        public override CmsPageContainer MapFromMulti(string sp, SqlDataReader reader, CmsPageContainer stepEntity, int index)
        {
            Guard.ArgumentNotEmpty(sp, "sp");
            Guard.ArgumentNotNull(reader, "reader");

            if (stepEntity == null)
            {
                stepEntity = new CmsPageContainer();
            }

            if (index == 0)
            {
                var stepPage = new CmsPage
                {
                    Id = reader.GetInt32(reader.GetOrdinal("PageId")),
                    SiteId = !reader.IsDBNull(reader.GetOrdinal("SiteId")) ?
                        reader.GetInt32(reader.GetOrdinal("SiteId")) :
                        new Nullable<int>(),
                    SiteGroupId = !reader.IsDBNull(reader.GetOrdinal("SiteGroupId")) ?
                        reader.GetInt32(reader.GetOrdinal("SiteGroupId")) :
                        new Nullable<int>(),
                    SystemLanguageId = !reader.IsDBNull(reader.GetOrdinal("SystemLanguageId")) ?
                       reader.GetInt32(reader.GetOrdinal("SystemLanguageId")) :
                       new Nullable<int>(),
                    PublicPageId = reader.GetInt32(reader.GetOrdinal("PublicPageId")),
                    PageName = reader.GetString(reader.GetOrdinal("PageName")),
                    PageUrl = reader.GetString(reader.GetOrdinal("PageUrl")),
                    PageTypeKey = reader.GetInt32(reader.GetOrdinal("PageTypeKey")),
                    PageBehaviourTypeKey = reader.GetInt32(reader.GetOrdinal("PageBehaviourTypeKey")),
                    UseFileCache = reader.GetBoolean(reader.GetOrdinal("UseFileCache")),
                    CreatedBy = reader.GetInt32(reader.GetOrdinal("CreatedBy")),
                    DateCreated = reader.GetDateTime(reader.GetOrdinal("DateCreated")),
                    LastUpdatedBy = !reader.IsDBNull(reader.GetOrdinal("LastUpdatedBy")) ?
                        reader.GetInt32(reader.GetOrdinal("LastUpdatedBy")) :
                        new Nullable<int>(),
                    DateLastUpdated = !reader.IsDBNull(reader.GetOrdinal("DateLastUpdated")) ?
                       reader.GetDateTime(reader.GetOrdinal("DateLastUpdated")) :
                       new Nullable<DateTime>(),
                    PublishStartDate = !reader.IsDBNull(reader.GetOrdinal("PublishStartDate")) ?
                        reader.GetDateTime(reader.GetOrdinal("PublishStartDate")) :
                        new Nullable<DateTime>(),
                    PublishEndDate = !reader.IsDBNull(reader.GetOrdinal("PublishEndDate")) ?
                        reader.GetDateTime(reader.GetOrdinal("PublishEndDate")) :
                        new Nullable<DateTime>(),
                    PageKey = reader.GetString(reader.GetOrdinal("PageKey"))
                };

                if (stepEntity.Pages == null)
                {
                    stepEntity.Pages = new CmsPage[] { stepPage };
                }
                else
                {
                    stepEntity.Pages = stepEntity.Pages.Concat(new CmsPage[] { stepPage }).ToList();
                }
            }
            else if (index == 1)
            {
                int pageId = reader.GetInt32(reader.GetOrdinal("PageId"));

                var stepPage = stepEntity.Pages.FirstOrDefault(p => p.Id == pageId);

                if (stepPage != null)
                {
                    if (!stepPage.IsMetaInformationLoaded)
                    {
                        stepPage.EntityMetaInformation = new CmsEntityMetaInformation();
                    }

                    stepPage.EntityMetaInformation.Metas.Add(
                        new CmsEntityMeta
                        {
                            Id = reader.GetInt32(reader.GetOrdinal("EntityMetaId")),
                            EntityId = stepEntity.Id,
                            EntityMetaFieldLink = new CmsEntityMetaFieldLink
                            {
                                Id = reader.GetInt32(reader.GetOrdinal("EntityMetaFieldLinkId")),
                                EntityMetaField = new CmsEntityMetaField
                                {
                                    Id = reader.GetInt32(reader.GetOrdinal("EntityMetaFieldId")),
                                    MetaFieldName = reader.GetString(reader.GetOrdinal("MetaFieldName")),
                                    MetaFieldType = reader.GetString(reader.GetOrdinal("MetaFieldType"))
                                }
                            },
                            EntityMetaValue = reader.GetString(reader.GetOrdinal("EntityMetaValue")),
                            IsDefault = reader.GetBoolean(reader.GetOrdinal("IsSystem"))
                        });
                }
            }
            else
            {
                if (sp.Equals("cms_sp_PageGetActiveRevisions", StringComparison.OrdinalIgnoreCase))
                {
                    if (index == 2)
                    {
                        int pageId = reader.GetInt32(reader.GetOrdinal("PageId"));

                        var stepPage = stepEntity.Pages.FirstOrDefault(p => p.Id == pageId);

                        if (stepPage != null)
                        {
                            stepPage.Workflow = new CmsWorkflow
                            {
                                Id = reader.GetGuid(reader.GetOrdinal("WorkflowId")),
                                Cycle = reader.GetInt32(reader.GetOrdinal("Cycle")),
                                ApproveDateDeadline = !reader.IsDBNull(reader.GetOrdinal("ApproveDateDeadline")) ?
                                    reader.GetDateTime(reader.GetOrdinal("ApproveDateDeadline")) :
                                    new Nullable<DateTime>(),
                                ReviewDateDeadline = !reader.IsDBNull(reader.GetOrdinal("ReviewDateDeadline")) ?
                                    reader.GetDateTime(reader.GetOrdinal("ReviewDateDeadline")) :
                                    new Nullable<DateTime>()
                            };

                            var workflowHistory = new CmsWorkflowHistory
                            {
                                Id = reader.GetInt32(reader.GetOrdinal("WorkflowHistoryId")),
                                WorkflowId = stepPage.WorkflowId.Value,
                                UserGroupId = !reader.IsDBNull(reader.GetOrdinal("UserGroupId")) ?
                                    reader.GetInt32(reader.GetOrdinal("UserGroupId")) :
                                    new Nullable<int>(),
                                AssignedUserGroup = !reader.IsDBNull(reader.GetOrdinal("GroupName")) ?
                                    reader.GetString(reader.GetOrdinal("GroupName")) :
                                    null,
                                AssignedUser = !reader.IsDBNull(reader.GetOrdinal("UserName")) ?
                                    reader.GetString(reader.GetOrdinal("UserName")) :
                                    null,
                                UserId = !reader.IsDBNull(reader.GetOrdinal("UserId")) ?
                                    reader.GetInt32(reader.GetOrdinal("UserId")) :
                                    new Nullable<int>(),
                                WorkflowState = reader.GetInt32(reader.GetOrdinal("WorkflowState")),
                                WorkflowData = !reader.IsDBNull(reader.GetOrdinal("WorkflowData")) ?
                                    reader.GetString(reader.GetOrdinal("WorkflowData")) :
                                    null,
                                WorkflowDataType = !reader.IsDBNull(reader.GetOrdinal("WorkflowDataType")) ?
                                   reader.GetString(reader.GetOrdinal("WorkflowDataType")) :
                                   null,
                                IsLatestState = reader.GetBoolean(reader.GetOrdinal("IsLatestState")),
                                Notes = !reader.IsDBNull(reader.GetOrdinal("Notes")) ?
                                    reader.GetString(reader.GetOrdinal("Notes")) :
                                    null,
                                CreatedBy = reader.GetInt32(reader.GetOrdinal("CreatedBy")),
                                DateCreated = reader.GetDateTime(reader.GetOrdinal("DateCreated")),
                                LastUpdatedBy = !reader.IsDBNull(reader.GetOrdinal("LastUpdatedBy")) ?
                                    reader.GetInt32(reader.GetOrdinal("LastUpdatedBy")) :
                                    new Nullable<int>(),
                                DateLastUpdated = !reader.IsDBNull(reader.GetOrdinal("DateLastUpdated")) ?
                                   reader.GetDateTime(reader.GetOrdinal("DateLastUpdated")) :
                                   new Nullable<DateTime>()
                            };

                            stepPage.Workflow.WorkflowHistory = new CmsWorkflowHistory[] { workflowHistory }.ToList();
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format("Stored procedure {0} can't return more than {1} result", sp, index));
                    }
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Stored procedure {0} can't return more than {1} result", sp, index));
                }
            }

            return stepEntity;
        }
    }
}